/*
 * 10/03/2007 
 */
package futbol.tacticas.concursantes2007.Chuky.chuky.futbolista;

import java.awt.Point;
import java.util.ArrayList;

import futbol.General;
import futbol.tacticas.concursantes2007.Chuky.chuky.entrenador.*;


/**
 * 
 * @author Joan Crosas
 */
public abstract class Futbolista {
	public static final int DISTANCIA_BALON_ENCIMA = 9;
	
	private int fuerza;
	private int numero;
	private int distanciaMaxPase;
	
	private Point posicionInicial;
	private Point posicion;
	private Balon balon;
	private Point[] posicionAmigos;
	private Point[] posicionEnemigos;
	
	
	private int tipoJuego;
	private boolean controlBalon;
	private InfoPosicion infoPosicion;

	private EntrenadorListener entrenadorListener;
	private Anotacion anotacion;
	
	/**
	 * 
	 */
	public Futbolista( int numero, int fuerza, Point posicionInicial, EntrenadorListener entrenadorListener ) {
		this.numero = numero;
		this.fuerza = fuerza;
		this.posicionInicial = posicionInicial;
		this.entrenadorListener = entrenadorListener;
		
		
		int t = ( fuerza * 3 ) - 4;
		distanciaMaxPase = fuerza * 3 * t - t * ( t - 1 ) / 2; 
		
		tipoJuego = Entrenador.DEFENSA;
		controlBalon = false;
	}
	
	public void refresh() {
		refreshBalonControlado();		
		infoPosicion = null;
		anotacion = null;
	}
	
	private void refreshBalonControlado() {
		// si tengo el control del baln
		if( controlBalon ) {
			// comprovamos que ningn otro jugador tenga el baln encima
			for( int i = 0; i < posicionEnemigos.length; i++ ) {
				// si el enemigo posee el baln, no lo controlamos
				if( posicionEnemigos[i].distance( balon.getPosicionBalon() ) < Futbolista.DISTANCIA_BALON_ENCIMA ) {
					controlBalon = false;
				}
			}
			for( int i = 0; i < posicionAmigos.length; i++ ) {
				// si algun amigo posee el baln no lo controlamos
				if( i != numero && posicionAmigos[i].distance( balon.getPosicionBalon() ) < Futbolista.DISTANCIA_BALON_ENCIMA ) {
					controlBalon = false;
				}
			}
		} else {
			// comprovamos si tengo el baln encima
			if( isBalonEncima() ) {
				controlBalon = true;
				entrenadorListener.nextAnotacion();
			}
		}
	}
	
	/**
	 * 
	 * @return
	 */
	public boolean isBalonControlado() {
		return controlBalon;
	}
	
	/**
	 * @return Devuelve true si tengo el baln
	 */
	public boolean isBalonEncima() {
		if( posicion.distance( balon.getPosicionBalon() ) < Futbolista.DISTANCIA_BALON_ENCIMA ) {
			return true;
		} 
		return false;
	}
	
	/**
	 * 
	 * @return Devuelve true si soy el que esta mas cerca del baln
	 */
	public boolean masCercanoBalon() {
		Point posicionBalon = balon.getPosicionBalon();
		double distanciaBalon = posicion.distance( posicionBalon );
		for( int i = 0; i < posicionAmigos.length; i++ ) {
			double distanciaAmigoBalon = posicionAmigos[i].distance( posicionBalon );
			if( distanciaAmigoBalon < distanciaBalon ) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 
	 * @return
	 */
	public InfoPosicion getInfoPosicion() {
		if( infoPosicion == null) {
			infoPosicion = new InfoPosicion( posicion, posicionAmigos, posicionEnemigos );
		}
		return infoPosicion;
	}
	
	/**
	 * 
	 * @return
	 */
	public Accion accionCorrer( Point irA ) {
		Accion accion = null;
		
		if( isBalonControlado() && isBalonEncima() ) {
			double angulo = General.getAngulo( posicion.x, posicion.y, irA.x, irA.y );
			accion = new AccionGolpearBalon( this, angulo, getDistanciaAutopase( 2 ) );
			
		} else if( isBalonControlado() ) {
			accion = new AccionCorrer( this, balon.getPosicionFutura( 3 ) );
			
		} else {
			
			for( int t = 1; t < 8 && balon.getVelocidadBalon() - t > 0 && accion == null; t++ ) {
				Point posicionBalonFuturo = balon.getPosicionFutura( t );
				
				double distanciaBalonFuturo = posicionBalonFuturo.distance( posicion );
				double distanciaFutbolistaFuturo = getDistanciaFutbolista( t );
				
				if( balon.getVelocidadBalon() - t < 15 && distanciaFutbolistaFuturo + 10 > distanciaBalonFuturo ) {
					accion = new AccionCorrer( this, posicionBalonFuturo );
				}
			}
			
			// si es el mas cercano a la bola vamos a por ella
			if( accion == null && masCercanoBalon() ) {
				accion = new AccionCorrer( this, balon.getPosicionFutura( 6 ) );
			}
			
			
			// sino llegamos al baln, nos vamos a la posicin que nos indican
			if( accion == null ) {
				accion = new AccionCorrer( this, irA );
			}
		}
		
		return accion;
	}
	
	public void repasarAnotacion( Anotacion anotacion ) {
		this.anotacion = anotacion;
	}
	
	/**
	 * reescriure la posici preferida pq mentres estiguem atacant la poguem modificar
	 * sense problemes
	 * @return
	 */
	public abstract Point getPosicionPreferida();
	
	/**
	 * 
	 * @param amigos
	 */
	public abstract void prepararAccion( ArrayList<Futbolista> amigos  );
	
	/**
	 * 
	 * @return
	 */
	public abstract Accion getAccion();
	
	
	/**
	 * La distancia de disparo del autopase depende de la velocidad del jugador,
	 * para poder atrapar el baln en un tiempo determinado debemos de satisfacer
	 * esta formula
	 * DistanciaDisparo = ( ( 2 * velJugador + t - 1 ) * 100 ) / fuerza * 12
	 * 
	 * @return Devuelve la distancia donde debe disparar el baln para 
	 * que el jugador pueda atrapar el baln en un tiempo determinado
	 */
	public double getDistanciaAutopase( int t ) {
		return ( ( 2 * ( 10 - fuerza ) + t - 1 ) * 100 ) / ( fuerza * 12 ) + 8;
	}
	
	/**
	 * Distancia maxima a la que el jugador puede desplazarse en un tiempo determinado
	 * DistanciaFutbolista = ( 10 - fuerza ) * t
	 * 
	 * @return la distancia que habra recorrido el jugador en un tiempo determinado
	 */
	public double getDistanciaFutbolista( int t ) {
		return ( 10 - fuerza ) * t;
	}
	
	public int getDistanciaMaxPase() {
		return distanciaMaxPase;
	}
	
	
	public Point getPosicion() {
		return posicion;
	}

	public void setPosicion(Point posicion) {
		this.posicion = posicion;
	}

	public Balon getBalon() {
		return balon;
	}
	public void setBalon( Balon balon ) {
		this.balon = balon;
	}
	
	public int getNumero() {
		return numero;
	}

	public Point[] getPosicionAmigos() {
		return posicionAmigos;
	}

	public void setPosicionAmigos(Point[] posicionAmigos) {
		this.posicionAmigos = posicionAmigos;
	}

	public Point[] getPosicionEnemigos() {
		return posicionEnemigos;
	}

	public void setPosicionEnemigos(Point[] posicionEnemigos) {
		this.posicionEnemigos = posicionEnemigos;
	}

	public int getFuerza() {
		return fuerza;
	}

	public Point getPosicionInicial() {
		return posicionInicial;
	}
	
	public int getTipoJuego() {
		return tipoJuego;
	}

	public void setTipoJuego(int tipoJuego) {
		this.tipoJuego = tipoJuego;
	}

	public Anotacion getAnotacion() {
		return anotacion;
	}

	public void setAnotacion( Anotacion anotacion ) {
		this.anotacion = anotacion;
	}
	
	public EntrenadorListener getEntrenadorListener() {
		return entrenadorListener;
	}
	
	
	

}
